//
//  JSONCoder.swift
//  MoonKit
//
//  Created by moon on 2019/3/1.
//  Copyright © 2019 moon. All rights reserved.
//

import Foundation
open class JSONCoder  {
	/// The output format to produce. Defaults to `[]`.
	open var outputFormatting: JSONSerialization.WritingOptions = []
	
	open var userInfo: [CodingUserInfoKey : Any] = [:]
	
	/// 编码对象,返回json格式的数据
	///
	/// - Parameter value: 被编码的对象
	/// - Returns: json格式数据,类型如下:NSArray,NSDictaionry,NSNumber,NSNull,NSString
	/// - Throws: CodingError中相应的错误
	open func tryEncode<T:Codable>(_ value:T) throws -> NSObject {
		let coder = _JSONCoder(codingOperation: .encode)
		coder.userInfo = userInfo
		guard let topLevel:NSObject = try coder.encodeJSON(value) else {
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) did not encode any values."))
		}
		return topLevel
	}
    open func tryEncode<T:Codable>(_ value:T) throws -> String? {
        let data:Data = try self.tryEncode(value)
        let s = String.init(data: data, encoding: .utf8)
        return s
    }
	/// 编码对象,返回json格式的数据
	///
	/// - Parameter value: 被编码的对象
	/// - Returns: 二进制格式的json格式数据
	/// - Throws: CodingError中相应的错误
	open func tryEncode<T:Codable>(_ value:T) throws -> Data {
		let coder = _JSONCoder(codingOperation: .encode)
		coder.userInfo = userInfo
		guard let topLevel:NSObject = try coder.encodeJSON(value) else {
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) did not encode any values."))
		}
		switch topLevel {
		case is NSNull:
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) encoded as null JSON fragment."))
		case is NSString:
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) encoded as string JSON fragment."))
		case is NSNumber:
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) encoded as number JSON fragment."))
		default:
			break
		}
		do {
			return try JSONSerialization.data(withJSONObject: topLevel, options: outputFormatting)
		} catch {
			throw CodingError.invalidValue(value,CodingError.Context(codingPath: [], debugDescription: "Unable to encode the given top-level value to JSON.", underlyingError: error))
		}
	}
    open func encode<T:Codable>(_ value:T) -> Data? {
        if let value:Data = try? self.tryEncode(value) {
            return value
        }
        return nil
    }
    open func encode<T:Codable>(_ value:T) -> NSObject? {
        var obj:NSObject?
        do {
            obj = try self.tryEncode(value)
        } catch {
            print("error:\(error)")
        }
        return obj
    }
    open func encode<T:Codable>(_ value:T) -> String? {
        var obj:String?
        do {
            obj = try self.tryEncode(value)
        } catch {
            print("error:\(error)")
        }
        return obj
    }
	
	/// 解码json数据为对象
	///
	/// - Parameters:
	///   - type: 待解码的对象类型
	///   - data: json格式的数据,支持以下类型:json格式的字符串,json格式的字符串Data,[Any],[String:Any],NSNumber,NSNull
	/// - Returns: 解码出来的对象
	/// - Throws: CodingError中相应的错误
	open func tryDecode<T:Codable>(_ type: T.Type, from data: Any) throws -> T {
		let topLevel: Any
		do {
			switch data {
			case let s as String:
				//json格式的字符串
				topLevel = try JSONSerialization.jsonObject(with: s.data(using: .utf8)!)
			case let d as Data:
				//json格式的字符串的二进制对象
				topLevel = try JSONSerialization.jsonObject(with: d)
			default:
				topLevel = data
			}
		} catch {
			throw CodingError.dataCorrupted(CodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
		}
		let coder = _JSONCoder(codingOperation: .decode)
		coder.userInfo = userInfo
		guard let value = try coder.decodeJSON(topLevel, as: type) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
		}
		return value
	}
	open func decode<T:Codable>(_ type: T.Type, from data: Any) -> T? {
        var value:T?
        do {
            value = try self.tryDecode(type, from: data)
        } catch {
            print("error:\(error)")
        }
        return value
    }
	/// 解码json数据,然后更新对象
	///
	/// - Parameters:
	///   - type: 待更新的对象
	///   - data: json格式的数据,支持以下类型:json格式的字符串,json格式的字符串Data,[Any],[String:Any],NSNumber,NSNull
	/// - Throws: CodingError中相应的错误
	open func tryDecode<T:Codable>(_ value: inout T, from data: Any) throws {
		let topLevel: Any
		do {
			switch data {
			case let s as String:
				//json格式的字符串
				topLevel = try JSONSerialization.jsonObject(with: s.data(using: .utf8)!)
			case let d as Data:
				//json格式的字符串的二进制对象
				topLevel = try JSONSerialization.jsonObject(with: d)
			default:
				topLevel = data
			}
		} catch {
			throw CodingError.dataCorrupted(CodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
		}
		let coder = _JSONCoder(codingOperation: .decode)
		coder.storage = topLevel
		coder.userInfo = userInfo
        try value.code(coder: coder)
	}
    open func decode<T:Codable>(_ value: inout T, from data: Any) {
        do{
            try self.tryDecode(&value, from: data)
        }catch{
            print("error:\(error)")
        }
    }
}

fileprivate class _JSONCoder : Coder {
	let codingOperation: CodingOperation
	var codingPath: [CodingKey] = []
	var userInfo: [CodingUserInfoKey : Any] = [:]
	var nilPresent: Bool = false
	
	/// 编解码的存储值的对象
	/// encode时,值为NSMutableArray,NSMutableDictionary,NSNull,NSString,NSNumber,NSArray,NSDictionary
	/// decode时,值为NSArray,NSDictionary,NSNull,NSString,NSNumber,[Any],[String:Any]
	fileprivate var storage: Any?
	
	fileprivate init(codingOperation: CodingOperation) {
		self.codingOperation = codingOperation
	}
	
	func container<Key>(keyedBy type: Key.Type) throws -> KeyedCodingContainer<Key> where Key : CodingKey {
		let storage:Any
		switch codingOperation {
		case .encode:
			if self.storage == nil {//容器初始为NSMutableDictionary
				storage = NSMutableDictionary()
				self.storage = storage
			} else {
				if let container = self.storage as? NSMutableDictionary {
					storage = container
				} else {
					//当前容器非NSMutableDictionary,创建新容器,进行覆盖
					storage = NSMutableDictionary()
					self.storage = storage
				}
			}
		case .decode:
			guard self.storage != nil else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "storage is nil"))
			}
			guard let container = self.storage as? _JSONDecodingKeyedContainerType else {
				throw CodingError._typeMismatch(at: codingPath, expectation: _JSONDecodingKeyedContainerType.self, reality: self.storage!)
			}
			storage = container
		}
		return KeyedCodingContainer(_JSONKeyedCodingContainer<Key>(coder: self, storage: storage, codingPath: []))
	}
	
	func unkeyedContainer() throws -> UnkeyedCodingContainer {
		let storage:Any
		switch codingOperation {
		case .encode:
			if self.storage == nil {//容器初始为NSMutableArray
				storage = NSMutableArray()
				self.storage = storage
			} else {
				if let container = self.storage as? NSMutableArray {
					storage = container
				} else {
					//当前容器非NSMutableArray,创建新容器,进行覆盖
					storage = NSMutableArray()
					self.storage = storage
				}
			}
		case .decode:
			guard self.storage != nil else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "storage is nil"))
			}
			guard let container = self.storage as? _JSONDecodingUnKeyedContainerType else {
				throw CodingError._typeMismatch(at: codingPath, expectation: _JSONDecodingUnKeyedContainerType.self, reality: self.storage!)
			}
			storage = container
		}
		return _JSONUnkeyedCodingContainer(coder: self, storage: storage , codingPath:[])
	}
	
	func singleValueContainer() throws -> SingleValueCodingContainer {
       return self
	}
	
	fileprivate func _decode(_ value: Any, as type: Bool.Type, codingPath: [CodingKey]) throws -> Bool? {
		guard !(value is NSNull) else { return nil }
		let v:Bool
		switch value {
		case let s as String:
			guard let tmp = Bool(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = Bool(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: String.Type, codingPath: [CodingKey]) throws -> String? {
		guard !(value is NSNull) else { return nil }
		switch value {
		case let s as String:
			return s
		case let number as NSNumber:
			return number.stringValue
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
	}
	fileprivate func _decode(_ value: Any, as type: Double.Type, codingPath: [CodingKey]) throws -> Double? {
		guard !(value is NSNull) else { return nil }
		let v:Double
		switch value {
		case let s as String:
			guard let tmp = type.init(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Float.Type, codingPath: [CodingKey]) throws -> Float? {
		guard !(value is NSNull) else { return nil }
		let v:Float
		switch value {
		case let s as String:
			guard let tmp = type.init(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Int.Type, codingPath: [CodingKey]) throws -> Int? {
		guard !(value is NSNull) else { return nil }
		
		let v:Int
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Int8.Type, codingPath: [CodingKey]) throws -> Int8? {
		guard !(value is NSNull) else { return nil }
		let v:Int8
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Int16.Type, codingPath: [CodingKey]) throws -> Int16? {
		guard !(value is NSNull) else { return nil }
		let v:Int16
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Int32.Type, codingPath: [CodingKey]) throws -> Int32? {
		guard !(value is NSNull) else { return nil }
		let v:Int32
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: Int64.Type, codingPath: [CodingKey]) throws -> Int64? {
		guard !(value is NSNull) else { return nil }
		let v:Int64
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: UInt.Type, codingPath: [CodingKey]) throws -> UInt? {
		guard !(value is NSNull) else { return nil }
		let v:UInt
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: UInt8.Type, codingPath: [CodingKey]) throws -> UInt8? {
		guard !(value is NSNull) else { return nil }
		let v:UInt8
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: UInt16.Type, codingPath: [CodingKey]) throws -> UInt16? {
		guard !(value is NSNull) else { return nil }
		let v:UInt16
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: UInt32.Type, codingPath: [CodingKey]) throws -> UInt32? {
		guard !(value is NSNull) else { return nil }
		let v:UInt32
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		
		return v
	}
	fileprivate func _decode(_ value: Any, as type: UInt64.Type, codingPath: [CodingKey]) throws -> UInt64? {
		guard !(value is NSNull) else { return nil }
		let v:UInt64
		switch value {
		case let s as String:
			guard let doubleValue = Double(s) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			guard let tmp = type.init(exactly: doubleValue) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
		case let number as NSNumber:
			guard let tmp = type.init(exactly: number) else {
				throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
			}
			v = tmp
			guard NSNumber(value: v) == number else {
				throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
			}
		default:
			throw CodingError._typeMismatch(at: codingPath, expectation: type, reality: value)
		}
		return v
	}

	fileprivate func _decodeCodable<T:Codable>(_ value: Any, as type: T.Type, codingPath: [CodingKey]) throws -> T? {
		guard !(value is NSNull) else { return nil }
        do {
            let coder = _JSONCoder(codingOperation: self.codingOperation)
            coder.storage = value
            let v = try T.initObject(from: coder)
            return v
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPath, current: originError)
            throw error
        } catch {
            throw error
        }
		
	}
	///解码value,JSON数据:NSNull,NSNumber,NSString,[Any],[String:Any]
	fileprivate func decodeJSON<T:Codable>(_ value: Any, as type: T.Type) throws -> T? {
		self.storage = value
		let v = try T.initObject(from: self)
		return v
	}
	///编码value,生成JSON数据:NSNull,NSNumber,NSString,NSArray,NSDictionary
	fileprivate func encodeJSON<T:Codable>(_ value: T) throws -> NSObject? {
        var tmp = value
        try tmp.code(coder: self)
		return self.storage as? NSObject
	}
	fileprivate func _encode(_ value: Bool, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: String, codingPath: [CodingKey]) throws -> NSObject {
		return NSString(string: value)
	}
	fileprivate func _encode(_ value: Double, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Float, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Int, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Int8, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Int16, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Int32, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: Int64, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: UInt, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: UInt8, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: UInt16, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: UInt32, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}
	fileprivate func _encode(_ value: UInt64, codingPath: [CodingKey]) throws -> NSObject {
		return NSNumber(value: value)
	}

	fileprivate func _encodeCodable<T:Codable>(_ value: T, codingPath: [CodingKey]) throws -> NSObject? {//不能命名为_encode,否则调用基础类型的_encode方法有可能会变成调用此方法
        do {
            let coder = _JSONCoder(codingOperation: self.codingOperation)
            var tmp = value
            try tmp.code(coder: coder)
            return coder.storage as? NSObject
        } catch let originError as CodingError {
            let error = CodingError(preCodingPath: codingPath, current: originError)
            throw error
        } catch {
            throw error
        }
	}
	
	
}
extension _JSONCoder : SingleValueCodingContainer {
    func superCoder() throws -> Coder {
        return self
    }
    
	func decodeNil() -> Bool {
		guard codingOperation == .decode else {
			return false
		}
		guard let storage = self.storage else {
			return false
		}
		return storage is NSNull
	}
	func expectDecodingNonNull<T>(_ type: T.Type) throws {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		guard let storage = self.storage else {
			throw CodingError.dataCorrupted(CodingError.Context(codingPath: codingPath, debugDescription: "storage is nil"))
		}
		if storage is NSNull {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
		}
	}
	func decode(_ type: Bool.Type) throws -> Bool {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: String.Type) throws -> String {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Double.Type) throws -> Double {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Float.Type) throws -> Float {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Int.Type) throws -> Int {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Int8.Type) throws -> Int8 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Int16.Type) throws -> Int16 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Int32.Type) throws -> Int32 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: Int64.Type) throws -> Int64 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: UInt.Type) throws -> UInt {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: UInt8.Type) throws -> UInt8 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: UInt16.Type) throws -> UInt16 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: UInt32.Type) throws -> UInt32 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode(_ type: UInt64.Type) throws -> UInt64 {
		try expectDecodingNonNull(type)
		return try self._decode(storage!, as: type, codingPath: codingPath)!
	}
	func decode<T>(_ type: T.Type) throws -> T where T : Codable {
		try expectDecodingNonNull(type)
		return try self._decodeCodable(storage!, as: type, codingPath: codingPath)!
	}
	
	func encodeNil() throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = NSNull()
	}
	func encode(_ value: Bool) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: String) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Double) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Float) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Int) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Int8) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Int16) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Int32) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: Int64) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: UInt) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: UInt8) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: UInt16) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: UInt32) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}
	func encode(_ value: UInt64) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		storage = try self._encode(value, codingPath: codingPath)
	}

	func encode<T>(_ value: T) throws where T : Codable {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		if let v = try self._encodeCodable(value, codingPath: codingPath) {
			storage = v
		}
	}
}

fileprivate class _JSONSuperCoder : _JSONCoder {
	private enum Reference {
		/// Referencing a specific index in an array container.
		case array(NSMutableArray, Int)
		
		/// Referencing a specific key in a dictionary container.
		case dictionary(NSMutableDictionary, String)
	}
	/// The encoder we're referencing.
	fileprivate let coder: _JSONCoder
	
	/// The container reference itself.
	private let reference: Reference
	
	fileprivate init(referencing coder: _JSONCoder, codingPath: [CodingKey], at index: Int, wrapping array: NSMutableArray) {
		self.coder = coder
		self.reference = .array(array, index)
		super.init(codingOperation: coder.codingOperation)
		self.userInfo = coder.userInfo
	}
	
	/// Initializes `self` by referencing the given dictionary container in the given encoder.
	fileprivate init(referencing coder: _JSONCoder, codingPath: [CodingKey], key: CodingKey, wrapping dictionary: NSMutableDictionary) {
		self.coder = coder
		self.reference = .dictionary(dictionary, key.stringValue)
		super.init(codingOperation: coder.codingOperation)
		self.userInfo = coder.userInfo
	}
	deinit {
		guard let storage = self.storage else {
			return
		}
		switch codingOperation {//延迟写入本数据到引用的容器中
		case .encode:
			switch self.reference {
			case .array(let array, let index):
				array[index] = storage
			case .dictionary(let dictionary, let key):
				dictionary[NSString(string: key)] = storage
			}
		case .decode:
			break
		}
	}
}

fileprivate typealias _JSONDecodingKeyedContainerType = [String:Any]
fileprivate struct _JSONKeyedCodingContainer<K : CodingKey> : KeyedCodingContainerProtocol {
	typealias Key = K
	private let coder: _JSONCoder
	
	/// 编解码存储值的容器
	/// encode时,值为NSMutableDictionary
	/// decode时,值为_JSONDecodingKeyedContainerType
	private let storage:Any
	
	init(coder: _JSONCoder,storage:Any , codingPath: [CodingKey]) {
		self.coder = coder
		self.codingOperation = coder.codingOperation
		self.storage = storage
		self.codingPath = codingPath
	}
	
	let codingOperation: CodingOperation
	
	var codingPath: [CodingKey]
	private var encodingStorage:NSMutableDictionary {
		return storage as! NSMutableDictionary
	}
	private var decodingStorage:_JSONDecodingKeyedContainerType {
		return storage as! _JSONDecodingKeyedContainerType
	}
	var allKeys: [Key] {
		switch codingOperation {
		case .encode:
			return encodingStorage.allKeys.compactMap{Key(stringValue: $0 as! String)}
		case .decode:
			return decodingStorage.keys.compactMap{Key(stringValue: $0)}
		}
	}
	
	func contains(_ key: Key) -> Bool {
		switch codingOperation {
		case .encode:
			return encodingStorage[key.stringValue] != nil
		case .decode:
			return decodingStorage[key.stringValue] != nil
		}
	}
	
	mutating func decodeNil(forKey key: Key) throws -> Bool {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		return entry is NSNull
	}
	mutating func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: String.Type, forKey key: Key) throws -> String {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	mutating func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decode(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}

	mutating func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Codable {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer { codingPath.removeLast() }
		guard let entry = decodingStorage[key.stringValue] else {
			throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
		}
		guard let value = try coder._decodeCodable(entry, as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) value but found null instead."))
		}
		return value
	}
	
	mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: K) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey {
		let storage:Any
		
		codingPath.append(key)
		defer { codingPath.removeLast() }
		
		switch codingOperation {
		case .encode:
			if let container = encodingStorage[key.stringValue] as? NSMutableDictionary{
				//已存在key键,已key对应的值为NSMutableDictionary,直接复用
				storage = container
			} else {
				storage = NSMutableDictionary()
				encodingStorage[key.stringValue] = storage
			}
		case .decode:
			guard let container = decodingStorage[key.stringValue] else {
				throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
			}
			guard container is _JSONDecodingKeyedContainerType else {
				throw CodingError._typeMismatch(at: self.codingPath, expectation: _JSONDecodingKeyedContainerType.self, reality: container)
			}
			storage = container
		}
		return KeyedCodingContainer(_JSONKeyedCodingContainer<NestedKey>(coder: coder, storage: storage , codingPath:[]))
	}
	
	mutating func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedCodingContainer {
		let storage:Any
		
		codingPath.append(key)
		defer { codingPath.removeLast() }
		
		switch codingOperation {
		case .encode:
			if let container = encodingStorage[key.stringValue] as? NSMutableArray{
				//已存在key键,且key对应的值为NSMutableArray,直接复用
				storage = container
			} else {
				storage = NSMutableArray()
				encodingStorage[key.stringValue] = storage
			}
		case .decode:
			guard let container = decodingStorage[key.stringValue] else {
				throw CodingError.keyNotFound(key, CodingError.Context(codingPath: self.codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
			}
			guard container is _JSONDecodingUnKeyedContainerType else {
				throw CodingError._typeMismatch(at: self.codingPath, expectation: _JSONDecodingUnKeyedContainerType.self, reality: container)
			}
			storage = container
		}
		return _JSONUnkeyedCodingContainer(coder: self.coder, storage: storage , codingPath:codingPath)
	}
	
	mutating func encodeNil(forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = NSNull()
	}
	mutating func encode(_ value: Bool, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: String, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Double, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Float, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Int, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Int8, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Int16, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Int32, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: Int64, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: UInt, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: UInt8, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: UInt16, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: UInt32, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	mutating func encode(_ value: UInt64, forKey key: Key) throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		encodingStorage[key.stringValue] = try coder._encode(value, codingPath: codingPath)
	}
	
	mutating func encode<T>(_ value: T, forKey key: Key) throws where T : Codable {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		if let v = try coder._encodeCodable(value, codingPath: codingPath) {
			encodingStorage[key.stringValue] = v
		}
	}
	
	mutating func superCoder() throws -> Coder {
		return try superCoder(forKey: Key(stringValue: "super")!)
	}
	
	mutating func superCoder(forKey key: Key) throws -> Coder {
		codingPath.append(key)
		defer {	codingPath.removeLast() }
		let storage:Any
		switch codingOperation {
		case .encode:
			let coder = _JSONSuperCoder(referencing: self.coder, codingPath: codingPath ,key: key, wrapping: encodingStorage)
			coder.storage = encodingStorage[key.stringValue]
			return coder
		case .decode:
			guard let container = decodingStorage[key.stringValue] else {
				throw CodingError.keyNotFound(key, CodingError.Context(codingPath: codingPath, debugDescription: "No value associated with key \(key.stringValue)."))
			}
			storage = container
			let coder = _JSONCoder(codingOperation: codingOperation)
			coder.userInfo = self.coder.userInfo
			coder.storage = storage
			return coder
		}
	}
}

fileprivate typealias _JSONDecodingUnKeyedContainerType = [Any]
fileprivate struct _JSONUnkeyedCodingContainer : UnkeyedCodingContainer {
	let coder: _JSONCoder
	
	/// 编解码存储值的容器
	/// encode时,值为NSMutableArray
	/// decode时,值为_JSONDecodingUnKeyedContainerType
	var storage:Any
	init(coder:_JSONCoder,storage:Any,codingPath:[CodingKey]) {
		self.coder = coder
		self.storage = storage
		self.codingOperation = coder.codingOperation
		self.codingPath = codingPath
	}
	
	var codingOperation: CodingOperation
	
	var codingPath: [CodingKey]
	var encodingStorage:NSMutableArray {
		return storage as! NSMutableArray
	}
	var decodingStorage:_JSONDecodingUnKeyedContainerType {
		return storage as! _JSONDecodingUnKeyedContainerType
	}
	var count: Int {
		switch codingOperation {
		case .encode:
			return encodingStorage.count
		case .decode:
			return decodingStorage.count
		}
	}
	
	var currentIndex: Int = 0
	
	mutating func decodeNil() throws -> Bool {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		
		try _checkDecodingIndex()
		if decodingStorage[currentIndex] is NSNull {
			currentIndex += 1
			return true
		} else {
			return false
		}
	}
	func _checkDecodingIndex() throws {
		guard codingOperation == .decode else {
			throw CodingError.invalidOperation
		}
		guard (0..<decodingStorage.count).contains(currentIndex) else {
			throw CodingError._indexOutOfRange(index: currentIndex, range: (0..<decodingStorage.count), at: codingPath)
		}
	}
	mutating func decode(_ type: Bool.Type) throws -> Bool {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: String.Type) throws -> String {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Double.Type) throws -> Double {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Float.Type) throws -> Float {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Int.Type) throws -> Int {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Int8.Type) throws -> Int8 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Int16.Type) throws -> Int16 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Int32.Type) throws -> Int32 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: Int64.Type) throws -> Int64 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: UInt.Type) throws -> UInt {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkDecodingIndex()
		guard  let value = try coder._decode(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		currentIndex += 1
		return value
	}
	
	mutating func decode<T>(_ type: T.Type) throws -> T where T : Codable {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		
		try _checkDecodingIndex()
		guard  let value = try coder._decodeCodable(decodingStorage[currentIndex], as: type, codingPath: codingPath) else {
			throw CodingError.valueNotFound(type, CodingError.Context(codingPath: codingPath, debugDescription: "Expected \(type) but found null instead."))
		}
		
		currentIndex += 1
		return value
	}
	
	mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedCodingContainer<NestedKey> where NestedKey : CodingKey {
		let storage:Any
		
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		
		switch codingOperation {
		case .encode:
			try _checkEncodingIndex()
			if let container = encodingStorage[currentIndex] as? NSMutableDictionary {
				//复用已有容器
				storage = container
			} else {
				storage = NSMutableDictionary()
				encodingStorage[currentIndex] = storage
			}
		case .decode:
			try _checkDecodingIndex()
			guard let container = decodingStorage[currentIndex] as? _JSONDecodingKeyedContainerType else {
				throw CodingError._typeMismatch(at: codingPath, expectation: _JSONDecodingKeyedContainerType.self, reality: decodingStorage[currentIndex])
			}
			storage = container
		}
		currentIndex += 1
		return KeyedCodingContainer(_JSONKeyedCodingContainer(coder: coder, storage: stat, codingPath: codingPath))
	}
	mutating func nestedUnkeyedContainer() throws -> UnkeyedCodingContainer {
		let storage:Any
		
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		
		switch codingOperation {
		case .encode:
			try _checkEncodingIndex()
			if let container = encodingStorage[currentIndex] as? NSMutableArray {
				//复用已有容器
				storage = container
			} else {
				storage = NSMutableArray()
				encodingStorage[currentIndex] = storage
			}
		case .decode:
			try _checkDecodingIndex()
			guard let container = decodingStorage[currentIndex] as? _JSONDecodingUnKeyedContainerType else {
				throw CodingError._typeMismatch(at: codingPath, expectation: _JSONDecodingUnKeyedContainerType.self, reality: decodingStorage[currentIndex])
			}
			storage = container
		}
		currentIndex += 1
		return _JSONUnkeyedCodingContainer(coder: coder, storage: stat, codingPath: codingPath)
	}
	func _checkEncodingIndex() throws {
		guard codingOperation == .encode else {
			throw CodingError.invalidOperation
		}
		guard (0...encodingStorage.count).contains(currentIndex) else {
			throw CodingError._indexOutOfRange(index: currentIndex, range: (0...encodingStorage.count), at: codingPath)
		}
	}
	mutating func _encodeValue(_ value:Any) throws {
		guard (0...encodingStorage.count).contains(currentIndex) else {
			throw CodingError._indexOutOfRange(index: currentIndex, range: (0...encodingStorage.count), at: codingPath)
		}
		encodingStorage[currentIndex] = value
		currentIndex += 1
	}
	mutating func encodeNil() throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		try _encodeValue(NSNull())
	}
	mutating func encode(_ value: Bool) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: String) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Double) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Float) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Int) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Int8) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Int16) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Int32) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: Int64) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: UInt) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: UInt8) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: UInt16) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: UInt32) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	mutating func encode(_ value: UInt64) throws {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		let v = try coder._encode(value, codingPath:codingPath)
		try _encodeValue(v)
	}
	
	mutating func encode<T>(_ value: T) throws where T : Codable {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		try _checkEncodingIndex()
		if let v = try coder._encodeCodable(value, codingPath:codingPath) {
			try _encodeValue(v)
		}
	}
	
	mutating func superCoder() throws -> Coder {
		codingPath.append(StringCodingKey(intValue: currentIndex))
		defer { codingPath.removeLast() }
		
		let storage:Any
		switch codingOperation {
		case .encode:
			try _checkEncodingIndex()
			let coder = _JSONSuperCoder(referencing: self.coder, codingPath: codingPath, at: currentIndex, wrapping: encodingStorage)
			if !isAtEnd {
				coder.storage = encodingStorage[currentIndex]
			}
			currentIndex += 1
			return coder
		case .decode:
			try _checkDecodingIndex()
			storage = decodingStorage[currentIndex]
			let coder = _JSONCoder(codingOperation: codingOperation)
			coder.userInfo = self.coder.userInfo
			coder.storage = storage
			currentIndex += 1
			return coder
		}
	}
	
}
